package tarantula.collector;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

import plume.Option;
import plume.Options;
import tarantula.util.Globals;

public class Main {
	
	@Option("The input dir of all transformed classes")
	public static String subject_dir = null;
	
	@Option("The output dir for all transformed junit classes")
	public static String junit_dir = null;
	
	@Option("The additoinal classpath used in running JUnit.")
	public static String additional_classpath = null;
	
	@Option("The JUnit execution class.")
	public static String junit_main = null;
	
	@Option("Show the help list.")
	public static boolean help = false;
	
	public static void main(String[] args) throws IOException, InterruptedException {
		parse_check_and_set_args(args);
		//start to execute the junit test
		new Main().execute_junit();
	}
	
	private void execute_junit() throws IOException, InterruptedException {
		List<String> cmdList = new ArrayList<String>();
		cmdList.add("cmd");
		cmdList.add("/C");
		cmdList.add("java");
		cmdList.add("-cp");
		cmdList.add(Globals.getClassPath() +
				(additional_classpath == null ? "" : (Globals.pathSep + additional_classpath)));
		// run the junit
		cmdList.add(junit_main);

		// launch the test process
		ProcessBuilder pb = new ProcessBuilder(cmdList.toArray(new String[0]));
		pb.directory(new File(junit_dir));
		Process process = pb.start();

		// get the output and store it into two separate tmp files
		InputStream stdStream = process.getInputStream();
		InputStream errStream = process.getErrorStream();
		BufferedReader stdReader = new BufferedReader(new InputStreamReader(
				stdStream));
		BufferedReader errReader = new BufferedReader(new InputStreamReader(
				errStream));

		File tmpStdFile = new File(junit_dir + Globals.fileSep
				+ "tmpStdOutput.tmp");
		File tmpErrFile = new File(junit_dir + Globals.fileSep
				+ "tmpErrOutput.tmp");
		PrintWriter stdWriter = new PrintWriter(tmpStdFile);
		PrintWriter errWriter = new PrintWriter(tmpErrFile);

		String stdLine = stdReader.readLine();
		while (stdLine != null) {
			stdWriter.println(stdLine);
			stdLine = stdReader.readLine();
		}

		String errLine = errReader.readLine();
		while (errLine != null) {
			errWriter.println(errLine);
			errLine = errReader.readLine();
		}

		stdWriter.close();
		errWriter.close();
		stdReader.close();
		errReader.close();

		process.waitFor();
	}
	
	private static void parse_check_and_set_args(String[] args) {
		//process the arguments
		Options options = new Options("Running JUnit tests: ", Main.class);
		String[] file_args = options.parse_or_usage(args);
		if(file_args.length != 0) {
			for(String errorMsg : file_args) {
				System.out.println(errorMsg);
				System.exit(1);
			}
		}
		
		//show the welcome page
		if(Main.help) {
			System.out.println("How to run junit tests!");
			System.out.println();
			options.print_usage();
			System.exit(1);
		}
		
		if(Main.subject_dir == null) {
			System.out.println("The input dir of all classes  transformed can not be null!");
			System.out.println();
			options.print_usage();
			System.exit(1);
		}
		
		if(Main.junit_dir == null) {
			System.out.println("The output dir for all transformed junit classes can not be null!");
			System.out.println();
			options.print_usage();
			System.exit(1);
		}
		
		if(Main.junit_main == null) {
			System.out.println("The junit main class can not be null!");
			System.out.println();
			options.print_usage();
			System.exit(1);
		}
	}
}
